package com.leizhi.demo.monitor.achieve.listener;

import com.leizhi.demo.monitor.pojo.FrameData;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description TCP RTP 监听器（解码部分）
 * @Version 1.0.0-SNAPSHOT
 * @Author leizhi
 * @Date 2025/5/17 10:57
 */
public class TcpRtpDecoderListener extends ByteToMessageDecoder {

    private static final Logger logger = LoggerFactory.getLogger(TcpRtpDecoderListener.class);
    /* 这个是自定义封装头，每个厂商的头不一样，主要是用来解决 TCP 粘包的问题 */
    private byte[] headerMagic;


    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> out) throws Exception {
        if (byteBuf.readableBytes() < 12) return; // 至少需要 12 字节 RTP 头部
        if (headerMagic == null) {
            headerMagic = new byte[2];
            byteBuf.readBytes(headerMagic);
            logger.info("已识别 Magic: {}", ByteBufUtil.hexDump(headerMagic));
        }

        int magicIndex = findMagic(byteBuf);
        if (magicIndex == -1) {
            return; // 没找到 Magic，等待更多数据
        }

        // 提取 Magic 前的数据包
        ByteBuf packet = byteBuf.readRetainedSlice(magicIndex);
        try {
            if (magicIndex > 0) {
                FrameData frameData = new FrameData(extractSsrc(packet));
                frameData.setNalUnits(parseNALUnits(packet));
                out.add(frameData);
            }
            byteBuf.skipBytes(headerMagic.length);
        } catch (Exception e) {
            logger.error("TCP 解码器发生异常, 准备丢弃该数据包. magic 位置：{}, 错误信息：{}, 数据包：{}", magicIndex, e.getMessage(), ByteBufUtil.hexDump(byteBuf));
            byteBuf.skipBytes(byteBuf.readableBytes());
        }
    }

    private Long extractSsrc(ByteBuf buf) {
        return ((long) (buf.getByte(8) & 0xFF) << 24)
                | ((buf.getByte(9) & 0xFF) << 16)
                | ((buf.getByte(10) & 0xFF) << 8)
                | (buf.getByte(11) & 0xFF);
    }

    private List<ByteBuf> parseNALUnits(ByteBuf payload) {
        List<ByteBuf> nalUnits = new ArrayList<>();
        int offset = 12;

        while (offset < payload.readableBytes()) {
            int nalUnitSize = payload.readableBytes() - offset;
            nalUnits.add(payload.slice(offset, nalUnitSize));
            offset += nalUnitSize;
        }

        return nalUnits;
    }

    private int findMagic(ByteBuf buf) {
        if (headerMagic == null || headerMagic.length == 0) {
            return -1; // Magic 未设置
        }

        int readerIndex = buf.readerIndex();
        int readableBytes = buf.readableBytes();
        int magicLength = headerMagic.length;

        for (int i = 0; i <= readableBytes - magicLength; i++) {
            boolean match = true;
            for (int j = 0; j < magicLength; j++) {
                if (buf.getByte(readerIndex + i + j) != headerMagic[j]) {
                    match = false;
                    break;
                }
            }
            if (match) {
                return i; // 完整匹配 Magic
            }
        }

        return -1; // 未找到 Magic
    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        logger.error("TCP 解码器发生异常", cause);
    }

}
